library(heatmaply)
## Loading required package: plotly
## Loading required package: ggplot2
##
## Attaching package: 'plotly'
## The following object is masked from 'package:ggplot2':
##
## last_plot
## The following object is masked from 'package:stats':
##
## filter
## The following object is masked from 'package:graphics':
##
## layout
## Loading required package: viridis
## Loading required package: viridisLite
##
## ======================
## Welcome to heatmaply version 1.5.0
##
## Type citation('heatmaply') for how to cite the package.
## Type ?heatmaply for the main documentation.
##
## The github page is: https://github.com/talgalili/heatmaply/
## Please submit your suggestions and bug-reports at: https://github.com/talgalili/heatmaply/issues
## You may ask questions at stackoverflow, use the r and heatmaply tags:
## https://stackoverflow.com/questions/tagged/heatmaply
## ======================
mtcars = mtcars #Se hace así porque en la actualidad "mtcars" es una base de datos nativa de R
heatmaply(mtcars, xlab = "Características", ylab = "Carros", main = "DATOS SIN PROCESAR (RAW DATA)")
normcars = normalize(mtcars)
heatmaply(normalize(mtcars), xlab = "Características", ylab = "Carros", main = "DATOS NORMALIZADOS POR Z-SCORE")
library(normalr)
lambdas = getLambda(mtcars)
normBoxcoxcars = normaliseData(mtcars, lambda = lambdas)
heatmaply(normaliseData(mtcars, lambda = lambdas), xlab = "Características", ylab = "Carros", main = "NORMALIZACIÓN BOX-COX DE LOS DATOS")
library(caret)
## Loading required package: lattice
preproc2 = preProcess(mtcars, method = c("range"), rangeBounds = c(-1, 1))
normMinMaxcars = predict(preproc2, mtcars)
summary(normMinMaxcars)
## mpg cyl disp hp
## Min. :-1.00000 Min. :-1.00000 Min. :-1.0000 Min. :-1.00000
## 1st Qu.:-0.57234 1st Qu.:-1.00000 1st Qu.:-0.7519 1st Qu.:-0.68551
## Median :-0.25106 Median : 0.00000 Median :-0.3754 Median :-0.49823
## Mean :-0.17527 Mean : 0.09375 Mean :-0.2037 Mean :-0.33083
## 3rd Qu.: 0.05532 3rd Qu.: 1.00000 3rd Qu.: 0.2716 3rd Qu.:-0.09541
## Max. : 1.00000 Max. : 1.00000 Max. : 1.0000 Max. : 1.00000
## drat wt qsec vs
## Min. :-1.00000 Min. :-1.00000 Min. :-1.00000 Min. :-1.000
## 1st Qu.:-0.70507 1st Qu.:-0.45372 1st Qu.:-0.43036 1st Qu.:-1.000
## Median :-0.13825 Median :-0.07338 Median :-0.23571 Median :-1.000
## Mean :-0.22897 Mean :-0.12848 Mean :-0.20268 Mean :-0.125
## 3rd Qu.: 0.06912 3rd Qu.: 0.07236 3rd Qu.: 0.04762 3rd Qu.: 1.000
## Max. : 1.00000 Max. : 1.00000 Max. : 1.00000 Max. : 1.000
## am gear carb
## Min. :-1.0000 Min. :-1.0000 Min. :-1.0000
## 1st Qu.:-1.0000 1st Qu.:-1.0000 1st Qu.:-0.7143
## Median :-1.0000 Median : 0.0000 Median :-0.7143
## Mean :-0.1875 Mean :-0.3125 Mean :-0.4821
## 3rd Qu.: 1.0000 3rd Qu.: 0.0000 3rd Qu.:-0.1429
## Max. : 1.0000 Max. : 1.0000 Max. : 1.0000
par(mfrow = c(1, 4))
boxplot(mtcars, main = "ORIGINAL")
boxplot(normcars, main = "Z-SCORES")
boxplot(normBoxcoxcars, main = "BOX-COX")
boxplot(normMinMaxcars, main = "MIN-MAX")
par(mfrow = c(1, 1))
Los métodos de discretización se pueden clasificar según el procedimiento que emplean. En este sentido, una primera clasificación se relaciona con el orden y distingue entre métodos de tipo Top-Down y Bottom-Up.
Métodos Top-Down Comienzan con una lista vacía de puntos de corte y añaden nuevos puntos a medida que avanza la discretización. La variable numérica se ordena, y los puntos de corte se agregan creando intervalos sucesivos, generando así categorías para la variable.
Métodos Bottom-Up Inician con una lista completa de todos los valores continuos como puntos de corte. Se busca reducir estos puntos de corte, agrupando valores cercanos y eliminando algunos, hasta alcanzar el número necesario de intervalos.
Una segunda dimensión para clasificar se relaciona con cómo se realiza la discretización: Dinámica y Estática.
Discretización Dinámica Algunos algoritmos, como los árboles de decisión, discretizan atributos continuos durante el proceso de clasificación, de manera recursiva y a medida que se aplica el procedimiento.
Discretización Estática Se realiza como un paso previo al procesamiento de datos. Los atributos continuos se discretizan antes de la tarea de clasificación.
En términos generales, no hay una ventaja clara entre la discretización dinámica y estática; son enfoques diferentes para abordar el problema.
Finalmente, al combinar los métodos Top-Down y Bottom-Up con la discretización dinámica y estática, se obtienen cuatro categorías principales de métodos de discretización:
Igual Amplitud: Genera intervalos con la misma amplitud para lograr una división homogénea de todo el rango de la variable.
Igual Frecuencia: Crea intervalos donde cada rango contiene aproximadamente la misma cantidad de casos observados de la variable.
Basados en Modelos (por ejemplo, 1R o chiMerge): Utilizan metodologías de modelos para realizar la discretización.
Procedimientos Algorítmicos (sin foco en amplitud ni frecuencia): Emplean algoritmos para lograr la discretización deseada y se consideran discretizaciones de aplicación de pseudomodelo.
Si \(k\) es el número de subintervalos en que se quiere partir el intervalo original, la expresión
\[C = \frac{X_{máx} - X_{mín}}{k}\]
generaría los siguientes puntos de corte:
\[X_{mín} + C, X_{mín} + 2C, X_{mín} + 3C, ..., X_{mín} + (k - 1)C\]
El argumento \(k\) (en la implementación en R, “nbins”) es el entero que especifica el número de contenedores a utilizar para la discretización. Por defecto, el número de contenedores se establece en \(N^{1/3}\), donde \(N\) es el tamaño de muestra. Los “números de contenedores” se refieren a la cantidad de divisiones o grupos utilizados al discretizar datos. En términos de cálculo diferencial e integral, el “número de contenedores” se relaciona con el ancho de cada subintervalo utilizado en la discretización de datos, siendo una medida que define la separación entre los diferentes grupos o divisiones
El criterio general para determinar el número de contenedores (o nbins en este contexto) al discretizar datos puede depender de varios factores, y no hay una regla única que se aplique en todos los casos. Algunos criterios comunes incluyen:
Fórmula de Sturges: \(k = 1 + log_2(n)\), usada cuando \(n \geq 100\).
Raíz cuadrada o cúbica de las filas de datos: Esta es una aproximación que se utiliza a menudo y se basa en la idea de encontrar un número de contenedores que sea proporcional a la cantidad de datos. Puede ser útil para conjuntos de datos de diferentes tamaños.
El uso de la raíz cuadrada o cúbica del número de observaciones (n) como criterio para determinar el número de contenedores (nbins) en un histograma es una práctica común, especialmente cuando se trabaja con conjuntos de datos pequeños. La idea detrás de esto es proporcionar un número de contenedores adecuado incluso con un conjunto de datos limitado (menos de 100 observaciones, muestra muy pequeña).
Cuando el conjunto de datos es pequeño, elegir un número demasiado grande de contenedores puede resultar en un histograma que refleje demasiado el ruido aleatorio de los datos. Por otro lado, elegir un número demasiado pequeño de contenedores puede no capturar la estructura subyacente de la distribución.
Por lo tanto, la raíz cuadrada o cúbica es una regla de oro para determinar un número inicial de contenedores que se ajuste a conjuntos de datos pequeños. Sin embargo, es importante destacar que esta es una regla general y puede ajustarse según el contexto específico y las características de los datos. Para conjuntos de datos más grandes, a menudo se recurre a reglas más elaboradas, como la Regla de Scott o la Regla de Freedman-Diaconis, que mencioné anteriormente, para proporcionar una estimación más precisa del ancho de banda o número de contenedores.
La Regla de Scott y la Regla de Freedman-Diaconis son métodos comunes para determinar el ancho de banda óptimo al construir un histograma. Ambos métodos tienen como objetivo proporcionar un número adecuado de contenedores que capturen la estructura de los datos de manera efectiva.
Regla de Scott
La Regla de Scott propone un ancho de banda (o número de contenedores) basado en la desviación estándar de los datos y el tamaño del conjunto de datos. La fórmula general es:
\[h = \frac{3.5⋅SD}{n^{1/3}}\]
donde:
\(h\) es el ancho de banda (o ancho de contenedor). \(SD\) es la desviación estándar de los datos. \(n\) es el número de observaciones en el conjunto de datos.
Regla de Freedman-Diaconis
La Regla de Freedman-Diaconis se basa en el rango intercuartil (IQR) de los datos. El ancho de banda se define como:
\[h = \frac{2⋅IQR}{n^{1/3}}\]
donde:
\(h\) es el ancho de banda o número de contenedores. \(IQR\) es el rango intercuartil de los datos (la diferencia entre el tercer cuartil y el primer cuartil). \(n\) es el número de observaciones.
Ambos métodos intentan proporcionar un ancho de banda adecuado que se ajuste a la variabilidad de los datos. La elección entre estos métodos a menudo depende de las características específicas del conjunto de datos y del propósito de la visualización. Estos métodos son utilizados comúnmente en la construcción de histogramas para garantizar una representación adecuada de la distribución de los datos.
Si se combinan Freedman-Diaconis y Scott, se llega a la fórmula:
\[C = \frac{X_{máx} - X_{mín}}{k}\]
Criterios estadísticos: Se pueden utilizar criterios estadísticos para determinar el número óptimo de contenedores. Esto puede incluir métodos que minimizan la varianza entre los contenedores o que están basados en la distribución de los datos.
Visualización: A veces, el número de contenedores se elige en función de cómo se visualizarán los datos. Un número inadecuado de contenedores puede hacer que un histograma sea difícil de interpretar visualmente.
La elección del número de contenedores a menudo implica un equilibrio entre la complejidad de los datos y la necesidad de presentarlos de manera comprensible. La mejor opción puede depender del contexto específico y del propósito del análisis.
library(infotheo)
data(USArrests)
nbins = sqrt(NROW(USArrests))
ew.data = discretize(USArrests, disc = "equalwidth", nbins = nbins)
En el contexto de la discretización con intervalos de igual frecuencia, el foco principal no radica tanto en buscar una representatividad en términos de longitud igual para la variable, sino en lograr una distribución homogénea de una cantidad similar de registros observados en cada uno de los valores categóricos definidos por la discretización.
El objetivo de la discretización con intervalos de igual frecuencia es dividir el rango total de los valores de la variable en intervalos de longitud variable, pero con el requisito fundamental de que cada intervalo contenga la misma cantidad de observaciones de la variable a discretizar. Esto puede ser desafiante ya que la cantidad de datos tendría que ser un múltiplo de la cantidad de clases (categoría o grupo al que pertenece cada registro de datos) deseadas. Se tolera hasta cierto punto que cada intervalo contenga aproximadamente el mismo número de instancias, y a veces se trabaja con frecuencias relativas o porcentajes para lograr una mejor aproximación y homogeneización en cada clase.
En este procedimiento, la longitud de los intervalos se define como una consecuencia secundaria de la acumulación de datos y no se utiliza la información de la clase para la discretización. Internamente, se propone comenzar con una acumulación de datos ordenados de menor a mayor. La cantidad total de datos se divide entre la cantidad de intervalos, estableciendo la frecuencia necesaria para cada intervalo. Luego, se contabilizan los datos ordenados, y cuando se alcanza la cantidad suficiente para cumplir con la frecuencia porcentual o de conteo deseada, se define una marca de clase para el primer intervalo. Este proceso se repite sucesivamente para determinar la longitud de cada intervalo.
Aunque este tipo de discretización es menos frecuente que la de igual amplitud, tiene aplicaciones específicas, especialmente cuando se desea garantizar que una variable categórica de entrada tenga un número igual de registros en cada clase. Esto puede reducir el sesgo de aprendizaje y predicción en algunos métodos de análisis de negocios. Bajo esta premisa, se considera un método útil y relevante, siendo el segundo más utilizado en comparación con la discretización de igual amplitud.
library(infotheo)
data(USArrests)
nbins = sqrt(NROW(USArrests))
ef.data = discretize(USArrests, disc = "equalfreq", nbins = nbins)
La discretización 1R sigue una metodología notablemente diferente a las anteriores. En primer lugar, al igual que en los casos anteriores, generalmente propone ordenar los datos de manera ascendente. Luego, lo que hace es dividir el rango total de los valores observados de la variable en intervalos. Estos límites de los intervalos se ajustan de acuerdo a la clase a la cual pertenece cada registro; esto significa que los límites de los intervalos se determinan considerando la clase a la que pertenece cada dato o, en otras palabras, la división de los intervalos se adapta según las categorías específicas de la variable de interés (por ejemplo, si estamos discretizando una variable relacionada con la altura de personas, las clases podrían ser “baja”, “media” y “alta”, y cada dato se asignaría a una de estas clases según su altura). En comparación con los métodos anteriores, se basa en la idea de la agrupación de valores, pero introduce una división por intervalos ajustada.
El método trabaja con una cantidad predefinida de clases preliminares y ajusta continuamente los límites de los intervalos para asegurar que cada intervalo tenga un cierto número mínimo de instancias, como por ejemplo, seis (excepto el último). Este ajuste de límites continúa hasta asegurar que el siguiente valor corresponda a una clase distinta a la clase mayoritaria del intervalo adyacente; esto significa que el proceso de ajustar los límites de los intervalos sigue adelante hasta que el siguiente valor de datos sea diferente a la clase que predomina en el intervalo vecino, es decir, se ajustan los límites para garantizar que los intervalos reflejen de manera precisa los cambios en las clases de los datos.
Un ejemplo simple de cómo este ajuste de límites continúa hasta asegurar que el siguiente valor corresponda a una clase distinta a la clase mayoritaria del intervalo adyacente se puede ver si suponemos que se está dividiendo edades en grupos. Si en un grupo la mayoría de las personas tienen entre 20 y 30 años, pero el próximo dato es una persona de 35 años, entonces ajustarías los límites del grupo para incluir esa nueva edad. Este ajuste continúa hasta que cada grupo tenga una mezcla de edades representativa y el próximo dato no encaje bien en el grupo vecino.
Esto implica un enfoque continuo y repetitivo sobre los datos, a diferencia de los métodos anteriores que proponían un enfoque más estático de discretización.
La discretización 1R tiene una dependencia significativa con la variable de clase, lo cual no era necesario en los casos anteriores. En términos de complejidad, se considera más compleja en comparación con las discretizaciones de igual longitud o frecuencia. Se utiliza comúnmente como un procedimiento de discretización complementario. En situaciones donde otras discretizaciones no parecen funcionar bien al convertirse en variables categóricas para modelos posteriores, la discretización 1R ofrece un enfoque diferente, potencialmente brindando una redistribución única de los valores en las variables.
Esta discretización proporciona una opción alternativa para abordar las variables de entrada, permitiendo un análisis diferente. Al proponer una discretización con resultados distintos, ofrece una posibilidad para enfocar la variable de entrada de manera diferente y, por lo tanto, puede tener una relación diferente con la variable objetivo en futuras aplicaciones, ya sea en métodos de aprendizaje supervisado o no supervisado.
EJEMPLO Supongamos que estamos discretizando la variable de ingresos en tres intervalos: [Bajo, Medio, Alto]. Además, tenemos la clase de salida “Aprobado” y “Reprobado” en una tarea. Veamos cómo se aplicaría la discretización 1R:
Ajuste Continuo con Dependencia de Clase 1. Inicialmente, consideramos tres intervalos: [Bajo], [Medio], [Alto]. 2. Evaluamos la distribución de clases en cada intervalo. 3. Notamos que [Bajo] tiene más instancias de “Reprobado”, mientras que [Alto] tiene más instancias de “Aprobado”. 4. Ajustamos los límites de los intervalos para que cada intervalo tenga una cantidad mínima de instancias, por ejemplo, seis, y siga siendo coherente con la distribución de clases.
Ajuste Continuo hasta que los Valores Correspondan a Clases Distintas Continuamos ajustando los límites hasta que el valor siguiente pertenezca a una clase distinta a la clase mayoritaria del intervalo adyacente. Por ejemplo, ajustamos [Bajo] hasta que el próximo valor sea “Aprobado”, asegurándonos de que el cambio sea significativo.
Este proceso continúa para lograr una discretización que refleje las diferencias en la distribución de clases y permita un análisis más detallado en relación con la variable de entrada.
library(infotheo)
data(USArrests)
nbins = sqrt(NROW(USArrests))
gew.data = discretize(USArrests, disc = "globalequalwidth", nbins = nbins)
La discretización Chi Merge se basa en fusionar intervalos con dos características fundamentales. Primero, los intervalos deben tener frecuencias relativas de clase parecidas; de lo contrario, se dividen. Segundo, intervalos adyacentes no deben tener frecuencias relativas de clase similares; de lo contrario, se unen. La metodología se apoya en el análisis de frecuencias relativas de clase y utiliza el estadístico chi cuadrado para evaluar la independencia.
El procedimiento implica calcular el chi cuadrado para cada par de intervalos adyacentes, fusionar los de menor chi cuadrado, y repetir hasta que los valores superen un umbral de significancia. El umbral se determina según el nivel de significancia y grados de libertad. Una vez que los intervalos superan el umbral, se concluye la discretización. Este método es más complejo que otros métodos de discretización.
\[\chi^2 = \sum_{j=1}^2 \sum_{i=1}^k \frac{(A_{ij} - E_{ij})^2}{E_{ij}}\]
dónde:
\(k\) es el número de clases.
\(A_{ij}\) es el número de datos del i-ésimo intervalo para la j-ésima clase.
\(E_{ij}\) es la frecuencia esperada de \(A_{ij}\) e igual a:
\[(R_i * C_j)/N\]
\(R_i\) esel número de datos en el i-ésimo intervalo.
\(C_j\) el número de datos en la j-ésima clase.
\(N\) es el número total de datos en los dos intervalos.
Si \(E_{ij} = 0\), se debe asignar a \(E_{ij}\) un valor pequeño, por ejemplo, 0.1.
EJEMPLO Supongamos que estamos discretizando una variable de edad en tres intervalos: [0-18], [19-35], [36-60]. Además, tenemos dos clases: “Joven” y “Adulto”. Veamos cómo aplicar los dos criterios:
Frecuencias Relativas de Clase Parecidas 1. Intervalo [0-18]: Joven (10), Adulto (5) 2. Intervalo [19-35]: Joven (8), Adulto (12) 3. Intervalo [36-60]: Joven (7), Adulto (8)
En este caso, las frecuencias relativas de clase son diferentes pero parecidas, por lo que los intervalos se mantienen unidos.
Intervalos Adyacentes sin Frecuencias Relativas de Clase Similares 1. Intervalo [0-18]: Joven (10), Adulto (5) 2. Intervalo [19-35]: Joven (2), Adulto (18) 3. Intervalo [36-60]: Joven (7), Adulto (8)
Aquí, el intervalo [19-35] tiene frecuencias relativas de clase muy diferentes, por lo que se decide dividirlo en dos intervalos: [19-26] y [27-35].
Este proceso continúa hasta que se cumplan ambos criterios para todos los intervalos adyacentes.
library(discretization)
data(iris)
disc = chiM(iris, alpha = 0.5)
chim.data = disc$Disc.data
library(broom)
#prpcomp(USArrests) Este formato no es apropiado, sino el siguiente:
prcomp(USArrests, scale = TRUE)
## Standard deviations (1, .., p=4):
## [1] 1.5748783 0.9948694 0.5971291 0.4164494
##
## Rotation (n x k) = (4 x 4):
## PC1 PC2 PC3 PC4
## Murder -0.5358995 -0.4181809 0.3412327 0.64922780
## Assault -0.5831836 -0.1879856 0.2681484 -0.74340748
## UrbanPop -0.2781909 0.8728062 0.3780158 0.13387773
## Rape -0.5434321 0.1673186 -0.8177779 0.08902432
prcomp(~Murder + Assault + Rape, data = USArrests, scale = TRUE)
## Standard deviations (1, .., p=3):
## [1] 1.5357670 0.6767949 0.4282154
##
## Rotation (n x k) = (3 x 3):
## PC1 PC2 PC3
## Murder -0.5826006 -0.5339532 0.6127565
## Assault -0.6079818 -0.2140236 -0.7645600
## Rape -0.5393836 0.8179779 0.1999436
plot(prcomp(USArrests))
plot(prcomp(USArrests, scale = TRUE))
summary(prcomp(USArrests, scale = TRUE))
## Importance of components:
## PC1 PC2 PC3 PC4
## Standard deviation 1.5749 0.9949 0.59713 0.41645
## Proportion of Variance 0.6201 0.2474 0.08914 0.04336
## Cumulative Proportion 0.6201 0.8675 0.95664 1.00000
biplot(prcomp(USArrests, scale = TRUE))
El conjunto de datos contiene información de un conjunto de propiedades de una empresa inmobiliaria. A continuación, se presenta la descripción de las variables.
knitr::include_graphics("IMAGEN.png")
Cargue este conjunto de datos en R y presente el código en R necesario para:
Realizar el heatmaply de la base de datos.
Normalizar la base de datos. Aplique los tres métodos de normalización.
Realizar la discretización de al menos 2 variables empleando al menos 3 métodos distintos.
Houses_to_rent = read.csv("houses_to_rent_v2.csv", header=TRUE, stringsAsFactors=FALSE)
library(heatmaply)
heatmaply(Houses_to_rent[1:100, c(1, 2, 3)], xlab = "Caracteríticas", ylab = "Ciudades", main = "DATOS SIN PROCESAR (RAW DATA)") #muy pesada la función para ejecutarla con un dataset tan grande
library(heatmaply)
normhouses = normalize(Houses_to_rent[1:100, c(2, 3)]) #para estandarizar el dataset que se usa y que las comparaciones entre metodologías de normalización tenga sentido. Se quita la primera columna, porque corresponde al nombre de las ciudades y la funcón de Box-Cox sólo acepta argumentos numéricos, no de caracter ni multinomiales (en caso de más de 2 categorías)
library(normalr)
normBoxcoxhouses = normaliseData(Houses_to_rent[1:100, c(2, 3)], lambda = getLambda(Houses_to_rent[1:100, c(1, 2, 3)], parallel = TRUE)) # es muy pesado usar esto para un conjunto de datos tan grande (tarda mucho, aún con un computador potente).
library(caret)
preproc3 = preProcess(Houses_to_rent[1:100, c(2, 3)], method = c("range"), rangeBounds = c(-1, 1))
normMinMaxhouses = predict(preproc3, Houses_to_rent[1:100, c(2, 3)])
par(mfrow = c(1, 4))
boxplot(Houses_to_rent[1:100, c(2, 3)], main = "ORIGINAL")
boxplot(normhouses, main = "Z-SCORES")
boxplot(normBoxcoxhouses, main = "BOX-COX")
boxplot(normMinMaxhouses, main = "MIN-MAX")
par(mfrow = c(1, 1))
library(infotheo)
nbins<- 1+ log2(NROW(normalize(Houses_to_rent))) #Esta fórmula se usa cuando n>=100
ew.rooms<- discretize(normalize(Houses_to_rent$rooms),"equalwidth", nbins)
ew.area <- discretize(normalize(Houses_to_rent$area),"equalwidth", nbins)
library(infotheo)
nbins<- 1+ log2(NROW(normalize(Houses_to_rent)))
ef.rooms <- discretize(normalize(Houses_to_rent$rooms),"equalfreq", nbins)
ef.area <- discretize(normalize(Houses_to_rent$area),"equalfreq", nbins)
library(infotheo)
nbins<- 1+ log2(NROW(normalize(Houses_to_rent)))
gew.rooms <- discretize(normalize(Houses_to_rent$rooms),"globalequalwidth", nbins)
table(gew.rooms)
## X
## 1 2 3 4 5 6 7 9 10 11 14
## 2454 2975 3269 1586 288 68 36 11 1 3 1
gew.area <- discretize(normalize(Houses_to_rent$area),"globalequalwidth", nbins)
table(gew.area)
## X
## 1 4 8 14
## 10689 1 1 1